package cn.yj.netty.message.chain;

import cn.yj.netty.common.Const;
import cn.yj.netty.message.convert.IProtocolMessageConvert;
import cn.yj.netty.support.test.MessageProtocol;
import cn.yj.netty.support.test.protocol.Header;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * 解析、验证协议包，将协议内容转换成业务对象
 *
 * @author 永健
 * @since 2022-02-16 14:22
 */
@Component
public class ProtocolMessageConvert extends AbstractMessageChain<String> implements IProtocolMessageConvert {

    private static final Logger log = LoggerFactory.getLogger(DispatchHandler.class);

    @Resource(type = AuthenticateHandler.class)
    @Override
    public AbstractMessageChain setNextChain(AbstractMessageChain nextChain) {
        return super.setNextChain(nextChain);
    }

    @Override
    public void message(ChannelHandlerContext channelHandlerContext, String msg) {
        super.handler(channelHandlerContext, msg);
    }

    @Override
    void doHandler(ChannelHandlerContext channelHandlerContext, final String msg) {
        log.info("开始解析协议包内容,host={}", getHost());
        // 消息是否符合规范
        if (checkMsg(msg)) {
            // 去除分隔符
            String replaceMsg = msg.replace(Const.DELIMITER_START, "").replace(Const.DELIMITER_END, "");

            // 转换成对象
            try {
                MessageProtocol messageProtocol = stringParseObject(replaceMsg);
                getNextChain().handler(channelHandlerContext, messageProtocol);
                return;
            } catch (Exception e) {
                log.info("协议包内容解析失败，关闭连接,host={}", getHost());
                e.printStackTrace();
            }
        } else {
            log.info("非法协议包，关闭连接,host={}", getHost());
        }
        channelHandlerContext.channel().close();
    }

    /**
     * 解析参数，原内容格式：
     * <p>
     * [!:--:]
     * tag: 0XF0DF88
     * version: 1.0
     * messageType: 1000
     * sessionId: 22912371093812
     * encrypt: 0
     * encode: UTF-8
     * host: 127.0.0.1
     * bodyType: JSON_STRING,
     * time: 1912031212
     * <p>
     * {"code":200,"msg":"请求成功"}
     * [:--:!]
     * <p>
     * 将内容转换成：MessageProtocol 对象
     *
     * @param msg
     */
    private MessageProtocol stringParseObject(String msg) {

        String[] strList = msg.split("\n");

        Header header = new Header();
        MessageProtocol messageProtocol = new MessageProtocol();
        Field[] declaredFields = header.getClass().getDeclaredFields();

        if (strList.length != declaredFields.length + 3) {
            throw new RuntimeException("协议包不符合规范");
        }

        Map<String, Object> headerMap = new HashMap<>();

        for (int i = 0; i < strList.length; i++) {
            String line = strList[i];
            if (!ObjectUtils.isEmpty(line)) {
                String[] split = line.split(":", 2);
                String key = split[0];
                String value = split[1];
                if (!"body".equals(key)) {
                    headerMap.put(key, value);
                } else {
                    messageProtocol.setBody(value);
                }
            }
        }
        messageProtocol.setHeader(JSONObject.parseObject(JSON.toJSONString(headerMap), Header.class));
        return messageProtocol;
    }

    /**
     * 校验分隔符
     *
     * @param msg
     */
    private boolean checkMsg(String msg) {
        return msg.indexOf(Const.DELIMITER_START) == 0 && msg.indexOf(Const.DELIMITER_END) == msg.length() - Const.DELIMITER_END.length();
    }


}
